/*
 * Copyright (c) 2025 [ByteDance Ltd. and/or its affiliates.] and/or its affiliates
 * SPDX-License-Identifier: LGPL v2.1+
*/
//
// Created by 郭鹤 on 2020/4/3.
// copy from cosmos

#pragma once
#include <memory>
#include <exception>
#include <string>
#include <utility>
#include <typeinfo>
#include <cstring>
#include <typeindex>

class FFAny {
public:
    FFAny() noexcept : _value_ptr(nullptr), _currentMemSize(0) {};
    ~FFAny();

    template <typename ValueType, std::enable_if_t<!std::is_same<std::decay_t<ValueType>, FFAny>::value && std::is_copy_constructible<std::decay_t<ValueType>>::value, int> = 0>
    FFAny(ValueType &&value) : _currentMemSize(sizeof(AnyImpl<std::decay_t<ValueType>>)) {
        uint8_t *buff = new uint8_t[_currentMemSize];
        _value_ptr = new(buff) AnyImpl<std::decay_t<ValueType>>(std::forward<ValueType>(value));
    }

    FFAny(const FFAny &other);
    FFAny(FFAny &&other) noexcept ;

    void swap(FFAny &rhs) noexcept;

    template <typename ValueType>
    std::enable_if_t<!std::is_same<std::decay_t<ValueType>, FFAny>::value && std::is_copy_constructible<std::decay_t<ValueType>>::value, FFAny &> operator=(ValueType &&rhs) {
        using Type = AnyImpl<std::decay_t<ValueType>>;
        constexpr size_t size = sizeof(Type);
        constexpr size_t MaxReservedSize = sizeof(void *) * 4;

        if (_value_ptr && size <= _currentMemSize && _currentMemSize - size <= MaxReservedSize) {
            _value_ptr->destruct();
            _value_ptr = new(_value_ptr) Type(std::forward<ValueType>(rhs));
        } else {
            *this = FFAny { std::forward<ValueType>(rhs) };
        }

        return *this;
    }

    FFAny &operator=(const FFAny &rhs);
    FFAny &operator=(FFAny &&rhs);

    bool hasValue() const noexcept;

    const char* name() const noexcept;

    void reset();

    bool IsNull() const { return !hasValue(); }

    template <typename U>
    bool Is() const {
        // 提出公共部分，避免过多实例化导致包大小增加。
        return isSameType(typeid(std::decay_t<U>));
    }

    // 不建议使用，类型不匹配会抛异常，可能导致crash。
    template <typename U>
    const U &AnyCast() const {
        using T = std::decay_t<U>;
        if (!Is<T>()) {
            // 禁用异常重构 @huangshixin.hsx2117
            printErrorLog();
        }

        return (static_cast<FFAny::AnyImpl<T> *>(_value_ptr)->_value);
    }

    // 不建议使用，类型不匹配会抛异常，可能导致crash。
    template <typename U>
    U &AnyCast() {
        using T = std::decay_t<U>;
        return const_cast<T &>(static_cast<const FFAny *>(this)->AnyCast<T>());
    }

    // vector，string，map等容器或大的对象，希望避免拷贝，可以使用这个接口。
    // 返回所存的对象的指针。
    template <typename ValueType>
    const ValueType *AnyCastPtr() const noexcept {
        using T = std::decay_t<ValueType>;
        if (Is<T>()) {
            return &(static_cast<FFAny::AnyImpl<T> *>(_value_ptr)->_value);
        }

        printErrorLog();
        return nullptr;
    }

    // vector，string，map等容器或大的对象，希望避免拷贝，可以使用这个接口。
    // 返回所存的对象的指针。
    template <typename ValueType>
    ValueType *AnyCastPtr() noexcept {
        using T = std::decay_t<ValueType>;
        return const_cast<T *>(const_cast<const FFAny *>(this)->AnyCastPtr<T>());
    }

    // 基本类型，智能指针等拷贝消耗较低的类型建议使用这个接口。
    template <typename ValueType>
    ValueType get() const {
        using T = std::decay_t<ValueType>;
        if (Is<T>()) {
            return (static_cast<FFAny::AnyImpl<T> *>(_value_ptr)->_value);
        }

        return {};
    }

    template <typename ValueType>
    bool get(ValueType& value) const {
        using T = std::decay_t<ValueType>;
        if (Is<T>()) {
            value = (static_cast<FFAny::AnyImpl<T> *>(_value_ptr)->_value);
            return true;
        }

        return false;
    }

    std::string toString() const;

private:
    bool isSameType(const std::type_info& info) const;

    void printErrorLog() const;

protected:
    struct AnyImplBase {
        enum Operation { Destruct, Clone};
        using TypeInfoFunc = void (*)(Operation, const AnyImplBase *, void **);

        // 不用虚函数，避免为每个不同的类型创建一个虚表。
        TypeInfoFunc typeInfoFunc = nullptr;
        std::type_index typeIndex;

#if defined(_DEBUG)
        // debug下增加虚析构函数，便于查看对象值
        virtual ~AnyImplBase() = default;
#endif

        AnyImplBase(TypeInfoFunc func1, const std::type_info &info) : typeInfoFunc(func1), typeIndex(info) {}

        void cloneToThis(FFAny *other) const { typeInfoFunc(Clone, this, reinterpret_cast<void **>(other)); }
        void destruct() { typeInfoFunc(Destruct, this, nullptr); }
    };

    template <typename ValueType>
    struct AnyImpl : public AnyImplBase {
        AnyImpl(const ValueType &value) : _value(value), AnyImplBase(&impl, typeid(ValueType)) {}
        AnyImpl(ValueType &&value) : _value(std::move(value)), AnyImplBase(&impl, typeid(ValueType)) {}

        static void impl(Operation which, const AnyImplBase *This, void **obj) {
            auto _this = reinterpret_cast<const AnyImpl *>(This);

            switch (which) {
                case AnyImplBase::Destruct: _this->~AnyImpl(); return;
                case AnyImplBase::Clone: {
                    auto *other = reinterpret_cast<FFAny *>(obj);
                    *other = _this->_value;
                    return;
                }
            }
        }

        ValueType _value;
    };

private:
    AnyImplBase *_value_ptr = nullptr;
    uint32_t _currentMemSize = 0;
};
